<template>
  <Form>
    <Row :gutter="15">
      <Col :span="6">
        <Form.Item label="数据库服务器">
          <Select v-model:value="currentDbIndex" :options="dbServers" @change="onRefresh" />
        </Form.Item>
      </Col>
      <Col :span="8">
        <label style="line-height: 34px">数据库地址：{{ dbAddress }}</label>
      </Col>
      <Col style="flex: 1; text-align: right" class="btn-group">
        <Button type="primary" danger :disabled="activePane != 'process'" @click="obortAllProcess"><DeleteFilled /> 终止所有</Button>
        <Button type="primary" @click="onRefresh"><SyncOutlined /> 刷新</Button>
      </Col>
    </Row>
  </Form>
  <Tabs v-model:activeKey="activePane" style="margin-top: 10px">
    <Tabs.TabPane tab="数据库执行进程" key="process">
      <Table :scroll="{ x: 600, y: detailHeight }" :rowKey="getRowKey" :expandFixed="true" :pagination="false" :columns="processColumns" :data-source="processDatas" bordered size="small">
        <template #bodyCell="{ column, record }">
          <template v-if="column.key == 'op'">
            <Button v-show="record.CanKill" type="primary" shape="round" danger @click="abortProcess(record.Id)"><DeleteFilled /> 终止</Button>
          </template>
        </template>
        <template #expandedRowRender="{ record }">
          <pre title="双击复制内容" style="max-height: 160px; overflow: auto; user-select: none" @dblclick="copyCommand(record)">{{ record.Command }}</pre>
        </template>
      </Table>
    </Tabs.TabPane>
    <Tabs.TabPane tab="数据库状态" key="status">
      <component :is="components[currentDbType]" :dbIndex="currentDbIndex" />
    </Tabs.TabPane>
  </Tabs>
</template>

<script setup>
  import { useStore } from 'vuex';
  import { useRoute } from 'vue-router';
  import { ref, reactive, inject, computed, watch, onMounted, defineAsyncComponent } from 'vue';
  import { Tabs, Form, Row, Col, Select, Button, Table } from 'ant-design-vue';
  import { DeleteFilled, SyncOutlined } from '@ant-design/icons-vue';

  const components = {
    mysql: defineAsyncComponent(() => import('./components/MySqlStatus.vue')),
    mssql: defineAsyncComponent(() => import('./components/MssqlStatus.vue'))
  };

  const $store = useStore();
  const route = useRoute();

  const http = inject('$http');
  const $modal = inject('$modal');
  const $message = inject('$message');
  const $eventBus = inject('$eventBus');
  const $copyText = inject('$copyText');

  const activePane = ref('process');
  const detailHeight = ref(800);
  const currentDbIndex = ref(0);
  const currentDbType = ref('mysql');

  const processDatas = ref([]);

  const dbServers = reactive([{ value: 0, display: 'N/A', type: 'mysql' }]);
  const processColumns = [
    { title: '序号', align: 'center', width: 60, customRender: ({ index }) => index + 1 },
    { title: '进程ID', dataIndex: 'Id', width: 80 },
    { title: '用户', dataIndex: 'User', width: 120, ellipsis: true },
    { title: '请求地址', dataIndex: 'Host', width: 160, ellipsis: true },
    { title: '数据库', dataIndex: 'db', width: 150, ellipsis: true },
    { title: '执行时间', width: 100, customRender: ({ record }) => record.Time + '毫秒' },
    { title: '状态', dataIndex: 'State', ellipsis: true },
    { title: '信息', ellipsis: true, customRender: ({ record }) => record.Info },
    { title: '操作', align: 'center', width: 120, fixed: 'right', key: 'op' }
  ];

  const dbAddress = computed(() => {
    return (dbServers[currentDbIndex.value] || { display: '-' }).display;
  });

  watch(activePane, val => {
    if (val == 'status') {
      $eventBus.emit('status-tab-changed', currentDbIndex.value);
    }
  }, { flush: 'post' });

  function getDbServers(initIndex) {
    http.get('/api/db/servers').then(rs => {
      let index = 0;

      dbServers.splice(
        0,
        dbServers.length,
        ...rs
          .filter(r => r.type != 'sqlite')
          .map(item => {
            return {
              label: item.display,
              value: index++,
              type: item.type,
              display: item.ip || item.Server
            };
          })
      );

      currentDbIndex.value = initIndex || 0;

      onRefresh();
    });
  }

  function onRefresh() {
    activePane.value = 'process';
    currentDbType.value = (dbServers[currentDbIndex.value] || { type: 'mysql' }).type;

    getProcessList();
  }

  function obortAllProcess() {
    let ids = (processDatas.value || []).filter(p => p.CanKill).map(p => p.Id);

    if (ids.length == 0) {
      $message.warning('没有需要终止的执行进程！');

      return;
    }

    abortProcess(ids.join(','));
  }

  function getProcessList() {
    processDatas.value.length = 0;

    http.post(`/api/db/${currentDbIndex.value || 0}/processlist`).then(rs => {
      processDatas.value = rs.datas;
    });
  }

  function abortProcess(id) {
    $modal.confirm({
      title: '警告',
      content: `是否确定终止${currentDbType.value == 'mssql' ? 'SQL Server' : 'MySQL'}进程？`,
      onOk: () => {
        http
          .post(`/api/db/${currentDbIndex.value}/killprocess`, {
            processId: id
          })
          .then(rs => {
            $modal.success({
              title: '提示',
              content: '操作成功！',
              onOk: () => {
                onRefresh();
              }
            });
          });
      }
    });
  }

  function getRowKey(record) {
    return record.Id;
  }

  function copyCommand(record) {
    $copyText(record.Command).then(() => {
      $message.success('命令复制！');
    });
  }

  function ResizeDetailPanel(area) {
    detailHeight.value = area.height - 175;
  }

  onMounted(() => {
    getDbServers(parseInt(route.query.dbIndex) || 0);

    let area = $store.state.area.content;

    ResizeDetailPanel(area);

    $eventBus.on('windowResizeChanged', client => ResizeDetailPanel(client));
  });
</script>

<style lang="less">
  .ant-table .ant-table-expanded-row-fixed {
    padding: 5px 0 0 5px;
  }
</style>
